package com.fenger.billbar.demo;

import java.awt.Button;
import java.awt.Color;
import java.awt.GraphicsConfiguration;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

import javax.imageio.ImageIO;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Material;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;

/**
 * 键盘控制下球的运动
 * 
 * @detail 在这里只考虑x,y方向上的平移和旋转
 * @author liubingzhao
 * 
 */
public class SphereTranswzKey extends JFrame implements ActionListener, KeyListener {
	private static final long serialVersionUID = 1L;
	private Button reset = new Button("reset");
	/** 球半径 */
	private float r = 0.050f;

	private double yloc = 0.0f;
	private double xloc = 0.0f;
	private double zloc = 0.0f;
	/** 模拟重力 */
	private double g = 9.8f;
	/** 模拟时间 */
	private double t = 0.0f;
	/** 模拟x速度 */
	private double vx = 0.005f;
	private double vy = 0.005f;
	private double vz = 0.0f;
	/**
	 * 球移动的方向(1,+x+y; 2,x; 3,+x-y; 4,-y; 5,-x-y; 6,-x; 7,-x+y; 8,+y)
	 * */
	private AtomicInteger direction = new AtomicInteger(0);
	private boolean k38 = false;
	private boolean k40 = false;
	private boolean k37 = false;
	private boolean k39 = false;

	private Timer timer;

	private TransformGroup objTrans;
	private Transform3D trans = new Transform3D();
	private javax.swing.JPanel drawingPanel;

	private void initComponents() {
		drawingPanel = new javax.swing.JPanel();
		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		setTitle("键盘控制下球的运动");
		drawingPanel.setLayout(new java.awt.BorderLayout());
		drawingPanel.setPreferredSize(new java.awt.Dimension(600, 800));
		getContentPane().add(drawingPanel, java.awt.BorderLayout.CENTER);

		pack();
	}

	public SphereTranswzKey() {
		initComponents();
		GraphicsConfiguration gc = SimpleUniverse.getPreferredConfiguration();
		// 定义显示图形的画布
		Canvas3D c = new Canvas3D(gc);
		c.addKeyListener(this);
		timer = new Timer(10, this);
		Panel p = new Panel();
		p.add(reset);

		reset.addActionListener(this);

		// 创建场景
		BranchGroup scene = createSceneGraph();
		// 定义一个简单的虚拟空间对象
		SimpleUniverse u = new SimpleUniverse(c);
		// 对物体进行投影
		u.getViewingPlatform().setNominalViewingTransform();
		u.addBranchGraph(scene);
		drawingPanel.add(c, java.awt.BorderLayout.CENTER);
		timer.start();
	}

	public BranchGroup createSceneGraph() {
		// 用来设置各种图形元素
		BranchGroup objRoot = new BranchGroup();
		// 设置背景
		Color3f backgroudColor3f = new Color3f(Color.GRAY);
		Background background = new Background(backgroudColor3f);
		objRoot.addChild(background);

		// 定义一个虚拟球范围来包容所以的图形元素
		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 1000.0);
		// color background
		/*
		 * Color3f bgColor = new Color3f(1.0f,1.0f,1.0f); Background bg = new
		 * Background(bgColor); bg.setApplicationBounds(bounds);
		 * objRoot.addChild(bg); // 定义光源的类型与颜色 Color3f directionalColor = new
		 * Color3f(1.1f,1.0f,1.0f);//光源颜色 Vector3f vec = new
		 * Vector3f(0.0f,0.0f,-1.0f);//用矢量定义光源的照射方向 DirectionalLight
		 * directionalLight = new DirectionalLight(directionalColor, vec);
		 * directionalLight.setInfluencingBounds(bounds);//设置光源的作用范围
		 * objRoot.addChild(directionalLight);
		 */
		// 定义坐标变换的节点
		objTrans = new TransformGroup();
		// 允许坐标变换值能够被读写
		objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		objRoot.addChild(objTrans);

		// 定义 通过鼠标旋转对三维形体实施坐标变换的功能
		MouseRotate behavior = new MouseRotate();// 定义鼠标旋转对象
		behavior.setTransformGroup(objTrans);// 将坐标变换对象加入到鼠标旋转对象中
		objRoot.addChild(behavior);// 将旋转功能加入到根节点中
		// 设置鼠标的旋转作用范围
		behavior.setSchedulingBounds(bounds);
		// 定义鼠标的放大功能
		MouseZoom behavior2 = new MouseZoom();
		behavior2.setTransformGroup(objTrans);
		objRoot.addChild(behavior2);
		behavior2.setSchedulingBounds(bounds);

		// 定义鼠标的平移功能
		MouseTranslate behavior3 = new MouseTranslate();
		behavior3.setTransformGroup(objTrans);
		// xloc = (double) behavior3.getXFactor();
		// xloc = behavior3.
		// yloc = (double) behavior3.getYFactor();
		objRoot.addChild(behavior3);
		behavior3.setSchedulingBounds(bounds);

		// 定义物体的外观特性
		Appearance app = new Appearance();
		BufferedImage image = null;
		try {
			image = ImageIO.read(ClassLoader.getSystemClassLoader().getResource("res/ball-hdpi/2.jpg"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		TextureLoader texloader = new TextureLoader(image, new String("RGB"));
		app.setTexture(texloader.getTexture());
		Material material = new Material();// 表面材质
		material.setDiffuseColor(new Color3f(0.0f, 0.0f, 0.0f));// 定义散射效果
		material.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		app.setMaterial(material);// 将材质属性加入到外观对象中
		// 定义球体
		Sphere sphere = new Sphere(r, -13, 100);
		sphere.setAppearance(app);
		objTrans.addChild(sphere);// 将球体加入到坐标对象中
		trans.setTranslation(new Vector3d(xloc, yloc, zloc));
		objTrans.setTransform(trans);

		Color3f light1Color = new Color3f(1.0f, 0.0f, 0.2f);
		Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
		DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction);
		light1.setInfluencingBounds(bounds);
		objRoot.addChild(light1);
		// 环境光
		Color3f ambientColor = new Color3f(1.0f, 1.0f, 1.0f);
		AmbientLight ambientLightNode = new AmbientLight(ambientColor);
		ambientLightNode.setInfluencingBounds(bounds);
		objRoot.addChild(ambientLightNode);
		objRoot.compile();// 对根节点进行优化预编译
		return objRoot;// 将根节点通过方法名返回
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == reset) {
			xloc = 0;
			yloc = 0;
			zloc = 0;
			t = 0.0f;
			vx = 0.0f;
			vy = 0.0f;
			vz = 0.0f;
			timer.stop();
		}

		switch (direction.get()) {
		case 1:
			yloc += vy;
			xloc += vx;
			break;
		case 2:
			xloc += vx;
			break;
		case 3:
			yloc -= vy;
			xloc += vx;
			break;
		case 4:
			yloc -= vy;
			break;
		case 5:
			yloc -= vy;
			xloc -= vx;
			break;
		case 6:
			xloc -= vx;
			break;
		case 7:
			yloc += vy;
			xloc -= vx;
			break;
		case 8:
			yloc += vy;
			break;
		default:
			break;
		}
		trans.setTranslation(new Vector3d(xloc, yloc, zloc));
		
		//球滚动计算
		/*Transform3D rot1 = new Transform3D();
		Transform3D rot2 = new Transform3D();
//		double r = Math.sqrt(xloc * xloc + yloc * yloc + zloc * zloc);
//		double alpha1 = Math.atan(xloc / zloc);
//		double alpha2 = Math.acos(yloc/r);	
		rot1.setTranslation(new Vector3d(xloc, yloc, zloc));
		rot1.rotX(direction.get() != 0 ? vy*Math.PI : 0);	// 绕Y旋转
		rot2.rotY(direction.get() != 0 ? vx*Math.PI : 0);	// 绕X旋转
		trans.mul(rot1);
		trans.mul(rot2);*/
		
		System.out.println("x:" + xloc + " y:" + yloc + " z:" + zloc + " t:" + t + "     vx:" + vx + " vy:" + vy + " vz:" + vz + " direction:" + direction);

		//trans.setTranslation(new Vector3d(xloc, yloc, zloc));
		objTrans.setTransform(trans);
	}

	public static void main(String[] args) {
		System.out.println("Program Started");
		new SphereTranswzKey().setVisible(true);
	}

	@Override
	public void keyTyped(KeyEvent e) {
		System.out.print("key is typed!\n");
	}

	@Override
	public void keyPressed(KeyEvent e) {
		System.out.print("key " + e.getKeyChar() + e.getKeyCode() + " is pressed!\n");
		switch (e.getKeyCode()) {
		case 38: {// 上-->沿y轴正向平移
			k38 = true;
			break;
		}
		case 40:// 下-->沿y轴负向平移
			k40 = true;
			break;
		case 37:// 左-->沿x轴负向平移
			k37 = true;
			break;
		case 39:// 右-->沿x轴正向平移
			k39 = true;
			break;
		default:
			break;
		}
		setDirection();
		 System.out.println("上:"+k38+"  下："+k40+"  左："+k37+"  右："+k39 +
		 "  Direction:"+direction);
	}

	@Override
	public void keyReleased(KeyEvent e) {
		System.out.print("key " + e.getKeyChar() + e.getKeyCode() + " is Released!\n");
		switch (e.getKeyCode()) {
		case 38: {// 上-->沿y轴正向平移
			k38 = false;
			break;
		}
		case 40:// 下-->沿y轴负向平移
			k40 = false;
			break;
		case 37:// 左-->沿x轴负向平移
			k37 = false;
			break;
		case 39:// 右-->沿x轴正向平移
			k39 = false;
			break;
		default:
			break;
		}
		setDirection();
		 System.out.println("上:"+k38+"  下："+k40+"  左："+k37+"  右："+k39 +
		 "  Direction:"+direction);
	}

	/**
	 * 38 37 39 40
	 * 
	 * @return direction
	 */
	private void setDirection() {
		if (k38 && k39 && !k37 && !k40) {
			direction.set(1);
		} else if (k39 && !k38 && !k40 && !k37) {
			direction.set(2);// 右
		} else if (k39 && k40 && !k37 && !k38) {
			direction.set(3);
		} else if (k40 && !k39 && !k37 && !k38) {
			direction.set(4);// 下
		} else if (k37 && k40 && !k38 && !k39) {
			direction.set(5);
		} else if (k37 && !k38 && !k40 && !k39) {
			direction.set(6);// 左
		} else if (k38 && k37 && !k39 && !k40) {
			direction.set(7);
		} else if (k38 && !k37 && !k39 && !k40) {
			direction.set(8);// 上
		} else {
			direction.set(0);
		}
	}

}
